﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO.Ports;
namespace SerialCommunicate
{
    public partial class Form1 : Form
    {
        private float X;
        private float Y;
        
        public Form1()
        {
            InitializeComponent();
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void setTag(Control cons)
        {
            foreach (Control con in cons.Controls)
            {
                con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;
                if (con.Controls.Count > 0)
                    setTag(con);
            }
        }
        private void setControls(float newx, float newy, Control cons)
        {
            foreach (Control con in cons.Controls)
            {

                string[] mytag = con.Tag.ToString().Split(new char[] { ':' });
                float a = Convert.ToSingle(mytag[0]) * newx;
                con.Width = (int)a;
                a = Convert.ToSingle(mytag[1]) * newy;
                con.Height = (int)(a);
                a = Convert.ToSingle(mytag[2]) * newx;
                con.Left = (int)(a);
                a = Convert.ToSingle(mytag[3]) * newy;
                con.Top = (int)(a);
                Single currentSize = Convert.ToSingle(mytag[4]) * Math.Min(newx, newy);
                con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
                if (con.Controls.Count > 0)
                {
                    setControls(newx, newy, con);
                }
            }

        }

        void Form1_Resize(object sender, EventArgs e)
        {
            float newx = (this.Width) / X;
            float newy = this.Height / Y;
            setControls(newx, newy, this);
            //this.Text = this.Width.ToString() + " " + this.Height.ToString();

        }

        private void button1_Click(object sender, EventArgs e) //打开串口按钮
        {
            try
            {
                serialPort1.PortName = comboBox1.Text;
                serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text,10);//十进制数据转换
                serialPort1.Open();
                button1.Enabled = false;//打开串口按钮不可用
                button2.Enabled = true;//关闭串口
            }
            catch {
                MessageBox.Show("端口错误,请检查串口", "错误");
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            for (int i = 1; i < 20; i++)
            {
                comboBox1.Items.Add("COM" + i.ToString());
            }
            comboBox1.Text = "COM1";//串口号多额默认值
            comboBox2.Text = "57600";//波特率默认            
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);//必须手动添加事件处理程序,串口响应函数，串口控件不能双击进入响应的方法（函数）
            this.BackColor = Color.White;//将窗口颜色设为变色

            X = this.Width;
            Y = this.Height;
            this.Resize += new EventHandler(Form1_Resize);
            setTag(this);
            Form1_Resize(new object(), new EventArgs());//x,y可在实例化时赋值,最后这句是新加的，在MDI时有用


        }

        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)//串口数据接收事件
        {
            if (!radioButton3.Checked)//如果接收模式为字符模式
            {
                string str = serialPort1.ReadExisting();//字符串方式读
                textBox1.AppendText(str);//添加内容
            }
            else { //如果接收模式为Hex接收
                byte data;
                data = (byte)serialPort1.ReadByte();//此处需要强制类型转换，将(int)类型数据转换为(byte类型数据，不必考虑是否会丢失数据
                string str = Convert.ToString(data, 16).ToUpper();//转换为大写十六进制字符串，例如0a转化成0A，主要是看着舒服
                textBox1.AppendText((str.Length == 1 ? "0" + str : str) + " ");//空位补“0”添加0X，例如,1转换成01，12转换成12   
                //上一句等同为：if(str.Length == 1)
                //                  str = "0" + str;
                //              else 
                //                  str = str;
                //              textBox1.AppendText(str);
            }
        }

        private void button2_Click(object sender, EventArgs e)//关闭串口按钮
        {
            try
            {
                serialPort1.Close();//关闭串口
                button1.Enabled = true;//打开串口按钮可用
                button2.Enabled = false;//关闭串口按钮不可用
            }
            catch (Exception err)//一般情况下关闭串口不会出错，所以不需要加处理程序
            {

            }
        }

        private void button3_Click(object sender, EventArgs e) //发送按钮
        {
            //try
            //{
            //    int tmp = int.Parse(textBox1.Text);
                byte[] Data = new byte[1];//只存储一个字节
                if (serialPort1.IsOpen)//判断串口是否打开，如果打开执行下一步操作
                {
                    if (textBox2.Text != "")//判断发送区是否为空
                    {
                        if (!radioButton1.Checked)//如果发送模式是字符模式
                        {
                            try
                            {
                                serialPort1.WriteLine(textBox2.Text);//写数据
                            }
                            catch (Exception err)
                            {
                                MessageBox.Show("串口数据写入错误", "错误");//出错提示
                                serialPort1.Close();
                                button1.Enabled = true;//打开串口按钮可用
                                button2.Enabled = false;//关闭串口按钮不可用
                            }
                        }
                        else//发送模式是Hex模式
                        {
                            //for (int i = 0; i < (textBox2.Text.Length - textBox2.Text.Length % 2) / 2; i++)//取余3运算作用是防止用户输入的字符为奇数个，循环发送（如果输入字符为0A0BB,则只发送0A,0B）
                            //{
                            //    Data[0] = Convert.ToByte(textBox2.Text.Substring(i * 2, 2), 16);//Convert.ToByte转换成字符，Substring(i * 2, 2)从Substring的i*2位的2位转换成16进制
                            //    serialPort1.Write(Data, 0, 1);//单字节写，从Data的0字节开始写入一个字节
                            //}
                            //if (textBox2.Text.Length % 2 != 0)//剩下一位单独处理
                            //{
                            //    Data[0] = Convert.ToByte(textBox2.Text.Substring(textBox2.Text.Length-1, 1), 16);//单独发送B（0B）
                            //    serialPort1.Write(Data, 0, 1);//发送
                            //}
                            for (int i = 0; i < textBox2.Text.Length; i++)//取余3运算作用是防止用户输入的字符为奇数个，循环发送（如果输入字符为0A0BB,则只发送0A,0B）
                            {
                                if (textBox2.Text.Substring(i, 1) != " ")
                                {
                                    Data[0] = Convert.ToByte(textBox2.Text.Substring(i, 2), 16);//Convert.ToByte转换成字符，Substring(i * 2, 2)从Substring的i*2位的2位转换成16进制
                                    serialPort1.Write(Data, 0, 1);//单字节写，从Data的0字节开始写入一个字节
                                    i++;
                                    i++;
                                }

                            }
                        }
                    }
                }
            //}
            //catch (Exception)
            //{
            //    MessageBox.Show("请正确输入数字");
            //}
           
        }

        private void button4_Click(object sender, EventArgs e)
        {
            string[] portlist = SerialPort.GetPortNames();
            for (int i = 0; i < portlist.Length; i++)
            {  
                comboBox1.Items.Add(portlist[i]);
            }
            comboBox1.Text = portlist[0];
        }

        private void button5_Click(object sender, EventArgs e)
        {
            //foreach (Control item in this.Controls)
            //{
            //    if (item is TextBox)
            //    {
            //        item.Text = string.Empty;
            //        //调用Clear方法也是可以的。
            //        //(item as TextBox).Clear();
            //    }
            //}
            (textBox1 as TextBox).Clear();
        }
    }
}
